package com.ruoyi.web.controller.common;

import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.system.domain.dto.FileUploadDTO;
import com.ruoyi.system.domain.vo.FileUploadVO;
import com.ruoyi.system.service.FileUploadService;
import org.apache.commons.io.FilenameUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.security.Security;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/system/files")
public class FileUploadController {

    @Resource
    private ServerConfig serverConfig;

    @Resource
    private FileUploadService fileUploadService;

    @Resource
    private RedisTemplate<String, Long> redisTemplate;

    /**
     * 通用上传请求（单个文件）
     */
    @PostMapping("/upload")
    @Transactional
    public AjaxResult uploadFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam @NotBlank(message = "业务类型不能为空") String businessType,
            @RequestParam(defaultValue = "", required = false) String businessId,
            @RequestParam @NotBlank(message = "文件类型不能为空") String fileType,
            @RequestParam (defaultValue = "", required = false) String uploadedBy
    ) throws Exception {
        try {
            // 校验文件
            if (file.isEmpty()) {
                return AjaxResult.error("上传文件不能为空");
            }
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            if (!Arrays.asList("docx","doc","pdf", "jpg", "jpeg", "png","xls","xlsx").contains(extension.toLowerCase())) {
                return AjaxResult.error("不支持的文件类型，仅允许 PDF、JPG、PNG、WORD、XLS、XLSX");
            }
            if (file.getSize() > 10 * 1024 * 1024) {
                return AjaxResult.error("文件大小不能超过 10MB");
            }

            // 生成 business_id（如果未提供）
            String finalBusinessId = businessId.isEmpty() ? generateCompanyId() : businessId;

            // 上传文件
            String filePath = RuoYiConfig.getUploadPath();
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;

            uploadedBy = String.valueOf(SecurityUtils.getUserId());
            // 保存到 file_upload 表
            FileUploadDTO dto = new FileUploadDTO();
            dto.setBusinessType(businessType);
            dto.setBusinessId(finalBusinessId);
            dto.setFileType(fileType);
            dto.setFileName(file.getOriginalFilename());
            dto.setFilePath(fileName);
            dto.setFileSize(file.getSize());
            dto.setFileExtension(extension);
            dto.setMimeType(file.getContentType());
            dto.setUploadedBy(uploadedBy);
            dto.setUploadTime(LocalDateTime.now());
            dto.setStatus(businessId.isEmpty() ? "temp" : "pending");
            dto.setAccessLevel("private");
            Long fileId = fileUploadService.addFileUpload(dto);

            // 返回结果
            AjaxResult ajax = AjaxResult.success();
            ajax.put("id", fileId);
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            ajax.put("businessId", finalBusinessId);
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error("上传失败: " + e.getMessage());
        }
    }

    /**
     * 通用上传请求（多个文件）
     */
    @PostMapping("/uploads")
    @Transactional
    public AjaxResult uploadFiles(
            @RequestParam("files") List<MultipartFile> files,
            @RequestParam @NotBlank(message = "业务类型不能为空") String businessType,
            @RequestParam(defaultValue = "", required = false) String businessId,
            @RequestParam @NotBlank(message = "文件类型不能为空") String fileType,
            @RequestParam (defaultValue = "", required = false) String uploadedBy
    ) throws Exception {
        try {
            if (files == null || files.isEmpty()) {
                return AjaxResult.error("上传文件列表不能为空");
            }

            // 生成 business_id（如果未提供）
            String finalBusinessId = businessId.isEmpty() ? generateCompanyId() : businessId;

            String filePath = RuoYiConfig.getUploadPath();
            List<FileUploadDTO> uploadedFiles = new ArrayList<>();

            for (MultipartFile file : files) {
                if (file.isEmpty()) {
                    continue;
                }
                String extension = FilenameUtils.getExtension(file.getOriginalFilename());
                if (!Arrays.asList("docx","doc","pdf", "jpg", "jpeg", "png").contains(extension.toLowerCase())) {
                    return AjaxResult.error("不支持的文件类型，仅允许 PDF、JPG、PNG、WORD");
                }
                if (file.getSize() > 10 * 1024 * 1024) {
                    return AjaxResult.error("文件 " + file.getOriginalFilename() + " 大小超过 10MB");
                }

                String fileName = FileUploadUtils.upload(filePath, file);
                String url = serverConfig.getUrl() + fileName;
                uploadedBy = String.valueOf(SecurityUtils.getUserId());
                FileUploadDTO dto = new FileUploadDTO();
                dto.setBusinessType(businessType);
                dto.setBusinessId(finalBusinessId);
                dto.setFileType(fileType);
                dto.setFileName(file.getOriginalFilename());
                dto.setFilePath(url);
                dto.setFileSize(file.getSize());
                dto.setFileExtension(extension);
                dto.setMimeType(file.getContentType());
                dto.setUploadedBy(uploadedBy);
                dto.setUploadTime(LocalDateTime.now());
                dto.setStatus(businessId.isEmpty() ? "temp" : "pending");
                dto.setAccessLevel("private");
                fileUploadService.addFileUpload(dto);

                uploadedFiles.add(dto);
            }

            AjaxResult ajax = AjaxResult.success();
            ajax.put("files", uploadedFiles.stream().map(dto -> new FileInfo(
                    dto.getId(), dto.getFilePath(), dto.getFileName(), FileUtils.getName(dto.getFileName()), dto.getFileName()
            )).collect(Collectors.toList()));
            ajax.put("businessId", finalBusinessId);
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error("上传失败: " + e.getMessage());
        }
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/{id}")
    @Transactional
    public AjaxResult deleteFile(@PathVariable Long id) {
        try {
            FileUploadVO fileUpload = fileUploadService.getFileUploadById(id);
            if (fileUpload == null) {
                return AjaxResult.error("文件记录不存在");
            }

            String currentUserId = getCurrentUserId();
            if (!fileUpload.getUploadedBy().equals(currentUserId)) {
                return AjaxResult.error("无权删除该文件");
            }

            fileUploadService.deleteFileUpload(id);

            String filePath = fileUpload.getFilePath();
            if (filePath.startsWith(serverConfig.getUrl())) {
                String relativePath = filePath.replace(serverConfig.getUrl(), "");
                FileUtils.deleteFile(RuoYiConfig.getUploadPath() + relativePath);
            }

            return AjaxResult.success("文件删除成功");
        } catch (Exception e) {
            return AjaxResult.error("删除失败: " + e.getMessage());
        }
    }

    /**
     * 查询单个文件记录
     */
    @GetMapping("/{id}")
    public AjaxResult getFileUpload(@PathVariable Long id) {
        FileUploadVO vo = fileUploadService.getFileUploadById(id);
        return AjaxResult.success(vo);
    }

    /**
     * 查询文件记录列表
     */
    @GetMapping("/list")
    public AjaxResult listFileUploads(
            @RequestParam(required = false) String businessType,
            @RequestParam(required = false) String businessId,
            @RequestParam(required = false) String fileType,
            @RequestParam(required = false) String status
    ) {
        List<FileUploadVO> list = fileUploadService.listFileUploads(businessType, businessId, fileType, status);
        return AjaxResult.success(list);
    }

    /**
     * 生成 business_id，格式：COMP_YYYYMMDD_XXX
     */
    private String generateCompanyId() {
        return IdUtil.simpleUUID();
//        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//        String key = "company_sequence:" + date;
//        Long sequence = redisTemplate.opsForValue().increment(key, 1);
//        if (sequence == 1) {
//            // 设置过期时间为 24 小时
//            redisTemplate.expire(key, 24, java.util.concurrent.TimeUnit.HOURS);
//        }
//        return String.format("COMP_%s_%03d", date, sequence);
    }

    private String getCurrentUserId() {
       return String.valueOf(SecurityUtils.getUserId());
    }

    // 辅助类
    private static class FileInfo {
        private Long id;
        private String url;
        private String fileName;
        private String newFileName;
        private String originalFilename;

        public FileInfo(Long id, String url, String fileName, String newFileName, String originalFilename) {
            this.id = id;
            this.url = url;
            this.fileName = fileName;
            this.newFileName = newFileName;
            this.originalFilename = originalFilename;
        }

        // Getters and Setters
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        public String getUrl() { return url; }
        public void setUrl(String url) { this.url = url; }
        public String getFileName() { return fileName; }
        public void setFileName(String fileName) { this.fileName = fileName; }
        public String getNewFileName() { return newFileName; }
        public void setNewFileName(String newFileName) { this.newFileName = newFileName; }
        public String getOriginalFilename() { return originalFilename; }
        public void setOriginalFilename(String originalFilename) { this.originalFilename = originalFilename; }
    }
}